package com.yst.sqlbuilder;

import com.yst.lambda.TableFieldFunc;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SQLOrderBy<T> implements ISQLExpression {

    @Getter
    private final SQLSelect<T> sqlSelect;
    public SQLOrderBy(SQLSelect<T> sqlSelect){
        this.sqlSelect=sqlSelect;
    }

    static class Order implements IOrderByItem {

        private final Object field;

        private final String orderMode;

        Order(Object field, String orderMode){
            this.field=field;
            this.orderMode=orderMode;
        }

        @Override
        public String generateExpression(GenerateParam param) {
            return getField().concat(" ").concat(orderMode);
        }

        @Override
        public String getField() {
            if (field instanceof TableFieldFunc) {
                return getEntitiesConfig().getFieldName((TableFieldFunc<?, ?>) field);
            }
            if (field instanceof String) {
                return (String) field;
            }
            throw new RuntimeException("order by not support type");
        }
    }
    private final List<IOrderByItem> orderByList=new ArrayList<>();
    public SQLOrderBy<T> orderBy(TableFieldFunc<T,?> field, OrderBy.OrderByMode orderByMode){
        orderByList.add(new Order(field,orderByMode.sql));
        return this;
    }

    public SQLSelect<T> asc(TableFieldFunc<T,?>...fields){
        for(TableFieldFunc<T,?> field:fields) {
            orderByList.add(new Order(field, OrderBy.OrderByMode.ASC.sql));
        }
        return sqlSelect;
    }
    public SQLSelect<T> desc(TableFieldFunc<T,?>...fields){
        for(TableFieldFunc<T,?> field:fields) {
            orderByList.add(new Order(field, OrderBy.OrderByMode.DESC.sql));
        }
        return sqlSelect;
    }

    @Override
    public String generateExpression(GenerateParam param) {
        if (orderByList.isEmpty()) return "";
        return "ORDER BY".concat(" ").concat(
                orderByList.stream()
                        .map(it->it.generateExpression(param))
                        .collect(Collectors.joining(","))
        );
    }
}
